package logic

import (
	"context"
	"github.com/gogap/logs"
	"log"
	"strconv"
	"time"
	"yundian/internel/app/dao"
	"yundian/internel/app/dao/memberdao"
	"yundian/internel/app/helper"
	"yundian/internel/app/helper/resphelper"
	"yundian/internel/app/models/loginlogs"
	"yundian/internel/app/models/membermodel"
	"yundian/internel/app/models/users"
	"yundian/internel/pkg/authorized"
	"yundian/internel/pkg/dingo"
	"yundian/internel/pkg/dingo/global"
	"yundian/internel/pkg/utils"
	"yundian/internel/pkg/wechatpay"
	"yundian/internel/pkg/wxpay"
)

type WxAuthLogic struct {
}

func NewWxAuthLogic() *WxAuthLogic {
	return &WxAuthLogic{}
}

// HandleLogicLogin 微信小程序登录逻辑
func (logic *WxAuthLogic) HandleLogicLogin(pdata *wxpay.PayData, appId string) (*resphelper.WxLoginResp, error) {
	var (
		tokenKey, token, unionid, nickName, phone string
		state                                     int8
		err                                       error
	)
	// ZM-Applet-Login-Token
	tokenKey = utils.Join(global.Const.Pre.TokenKeyPre, "-Applet-Login-Token", pdata.Get("openid"))
	rdbSessionKey := utils.Join(pdata.Get("openid"), "-sessionKey") // 保存sessionKey用于解密
	global.Rdb.Set(context.Background(), rdbSessionKey, pdata.Get("session_key"), time.Hour*24)

	// 验证token是否过期
	//token = global.Rdb.Get(context.Background(), tokenKey).Val()
	//if token != "" && global.Rdb.TTL(context.Background(), tokenKey).Val().Microseconds() > 10 {
	//	log.Println(token)
	//	return &resphelper.WxLoginResp{
	//		Token:      token,
	//		OpenId:     pdata.Get("openid"),
	//		UnionId:    pdata.Get("unionid"),
	//		ErrCode:    pdata.Get("errcode"),
	//		ErrMsg:     pdata.Get("errmsg"),
	//		//SessionKey: pdata.Get("session_key"),
	//	}, err
	//}

	// 校验用户是否存在
	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(pdata.Get("openid"), appId).Unwrap().(*membermodel.MembersModel)

	if memInfo.ID > 0 {
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "")
		unionid = memInfo.Unionid
		nickName = memInfo.NickName
		phone = memInfo.Phone
		state = memInfo.State
	} else {
		// 新增用户
		m := membermodel.New().Mutate(
			membermodel.WithXcxOpenid(pdata.Get("openid")),
			membermodel.WithUnionid(pdata.Get("unionid")),
			membermodel.WithRegFrom("wx_xcx"),
			membermodel.WithCreateAt(dingo.Time(time.Now().Unix())),
			membermodel.WithUUID(utils.Str2Md5(helper.GenerateUUID())),
			membermodel.WithAppId(appId),
		)
		memInfo := memberdao.NewMemberDao().InsertMember(m).Unwrap().(*membermodel.MembersModel)
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "") // 生成token
		unionid = pdata.Get("unionid")
		nickName = pdata.Get("nickName")
		state = memInfo.State
	}

	// 将token保存到redis
	global.Rdb.Set(context.Background(), tokenKey, token, time.Hour*24) // 过期时间18小时

	return &resphelper.WxLoginResp{
		Token:    token,
		OpenId:   pdata.Get("openid"),
		UnionId:  unionid,
		ErrCode:  pdata.Get("errcode"),
		ErrMsg:   pdata.Get("errmsg"),
		NickName: nickName,
		Phone:    phone,
		State:    state,
		//SessionKey: pdata.Get("session_key"),
	}, err
}

func (logic *WxAuthLogic) HandleLogicLoginWifi(pdata *wxpay.PayData, appId string) (*resphelper.WxLoginResp, error) {
	var (
		tokenKey, token, unionid, nickName, phone string
		state                                     int8
		err                                       error
	)
	// ZM-Applet-Login-Token
	tokenKey = utils.Join(global.Const.Pre.TokenKeyPre, "-Wifi-Applet-Login-Token", pdata.Get("openid"))
	rdbSessionKey := utils.Join(pdata.Get("openid"), "-sessionKey") // 保存sessionKey用于解密
	global.Rdb.Set(context.Background(), rdbSessionKey, pdata.Get("session_key"), time.Hour*24)

	// 验证token是否过期
	//token = global.Rdb.Get(context.Background(), tokenKey).Val()
	//if token != "" && global.Rdb.TTL(context.Background(), tokenKey).Val().Microseconds() > 10 {
	//	log.Println(token)
	//	return &resphelper.WxLoginResp{
	//		Token:      token,
	//		OpenId:     pdata.Get("openid"),
	//		UnionId:    pdata.Get("unionid"),
	//		ErrCode:    pdata.Get("errcode"),
	//		ErrMsg:     pdata.Get("errmsg"),
	//		//SessionKey: pdata.Get("session_key"),
	//	}, err
	//}

	// 校验用户是否存在
	memInfo := memberdao.NewMemberDao().
		GetMemberInfoByOpenidAndAppId(pdata.Get("openid"), appId).Unwrap().(*membermodel.MembersModel)

	if memInfo.ID > 0 {
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "")
		unionid = memInfo.Unionid
		nickName = memInfo.NickName
		phone = memInfo.Phone
		state = memInfo.State
	} else {
		// 新增用户
		m := membermodel.New().Mutate(
			membermodel.WithXcxOpenid(pdata.Get("openid")),
			membermodel.WithUnionid(pdata.Get("unionid")),
			membermodel.WithRegFrom("wx_xcx"),
			membermodel.WithCreateAt(dingo.Time(time.Now().Unix())),
			membermodel.WithUUID(utils.Str2Md5(helper.GenerateUUID())),
			membermodel.WithAppId(appId),
		)
		memInfo := memberdao.NewMemberDao().InsertMember(m).Unwrap().(*membermodel.MembersModel)
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "") // 生成token
		unionid = pdata.Get("unionid")
		nickName = pdata.Get("nickName")
		state = memInfo.State
	}

	// 将token保存到redis
	global.Rdb.Set(context.Background(), tokenKey, token, time.Hour*24) // 过期时间18小时

	return &resphelper.WxLoginResp{
		Token:    token,
		OpenId:   pdata.Get("openid"),
		UnionId:  unionid,
		ErrCode:  pdata.Get("errcode"),
		ErrMsg:   pdata.Get("errmsg"),
		NickName: nickName,
		Phone:    phone,
		State:    state,
		//SessionKey: pdata.Get("session_key"),
	}, err
}

// UpdateMemberInfo 更新微信小程序会员信息
func (logic *WxAuthLogic) UpdateMemberInfo(userInfo *wechatpay.WxUserInfo, userId int) bool {
	m := membermodel.New().Mutate(
		membermodel.WithID(userId),
		membermodel.WithUnionid(userInfo.UnionID),
		membermodel.WithUpdateAt(dingo.Time(time.Now().Unix())),
		membermodel.WithNickName(userInfo.NickName),
		membermodel.WithBalance(0),
		membermodel.WithHeadimgurl(userInfo.AvatarURL),
		membermodel.WithCity(userInfo.City),
		membermodel.WithCountry(userInfo.Country),
		membermodel.WithProvince(userInfo.Province),
		membermodel.WithSex(int8(userInfo.Gender)),
	)
	if ok := memberdao.NewMemberDao().UpdateMemberInfoById(m).Unwrap().(bool); ok {
		return true
	}
	return false
}

// 更新手机号码
func (logic *WxAuthLogic) UpdateMemberPhone(phone string, userId int) bool {
	m := membermodel.New().Mutate(
		membermodel.WithID(userId),
		membermodel.WithPhone(phone),
		membermodel.WithUpdateAt(dingo.Time(time.Now().Unix())),
		membermodel.WithNickName(phone),
	)
	if ok := memberdao.NewMemberDao().UpdateMemberInfoById(m).Unwrap().(bool); ok {
		return true
	}
	return false
}

// 公众号 - 验证授权的微信是否绑定了帐号密码
func (logic *WxAuthLogic) VerifyWxUserInfo(code, ip string) (string, string, authorized.ResWebAccessToken, error) {
	log.Println(code)
	loginTime := dingo.Time(time.Now().Unix())
	var token string
	var err error
	resp, err := authorized.GetWebAccessToken(code, global.Cfg.Wx.AppId, global.Cfg.Wx.AppSecret)
	log.Println("打印测试 openid", resp.Openid)
	log.Println("打印测试 access-token", resp.AccessToken)
	log.Println("打印测试 access-token", resp.Unionid)
	if err != nil {
		userInfo := users.New()
		dingo.Task(logic.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "公众号商户登录", "微信授权失败" + err.Error(), userInfo.Phone) // 记录登录日志
		return "", "", resp, err
	}
	//var accessToken, refreshToken, openid, unionid string
	//var expiresIn int
	//openid = resp.Openid
	//unionid = resp.Unionid
	//refreshToken = resp.RefreshToken
	//accessToken = resp.AccessToken
	//expiresIn = resp.ExpiresIn

	// 保存access_token
	wxTokenKey := utils.Join("WxAccess-Token-", resp.Openid)
	log.Println(wxTokenKey)
	global.Rdb.Set(context.Background(), wxTokenKey, resp.AccessToken, 0)

	// 判断openid是否有绑定用户，有则直接登录
	//count := dao.NewUserDao().GetUserCountByopenid(resp.Openid).Unwrap().(int64)
	// 获取用户信息
	userInfo := dao.NewUserDao().GetUserInfoByopenid(resp.Openid).Unwrap().(*users.UserModel)
	logs.Info("=======微信授权登录-用户信息：============", userInfo)
	if userInfo.ID > 0 && userInfo.IsBind == 1 { // openid 有绑定用户, 直接返回登录信息
		// 生成 Token
		key := utils.Join("Yd-Wechat-Login-Token", strconv.Itoa(userInfo.ID))
		token, err = dingo.GenerateToken(userInfo.ID, userInfo.Name, userInfo.IsAdmin, 0, userInfo.IsPlace, userInfo.IsDraw, "")

		global.Rdb.Set(context.Background(), key, token, time.Hour*1) // 过期时间48小时

		dingo.Task(logic.updateUserLoginInfo, func() {}, userInfo.ID, ip, loginTime) // 更新登录信息
		dingo.Task(logic.updateUserLoginCount, func() {}, userInfo.ID)               // 更新登录次数
		//dingo.Task(logic.insertUserLoginLog, func() {}, userInfo, ip, loginTime) // 记录登录日志
		dingo.Task(logic.insertUserLoginLog, func() {}, userInfo, ip, loginTime, "公众号商户登录", "登录成功", userInfo.Phone) // 记录登录日志
		return token, resp.Openid, resp, nil
	}

	return "", resp.Openid, resp, nil
}

// UpdateUserLoginInfo 更新登录信息 (登录IP、登录时间)
func (logic *WxAuthLogic) updateUserLoginInfo(params ...interface{}) {
	id := params[0].(int)
	ip := params[1].(string)
	t := params[2].(dingo.Time)
	dao.NewUserDao().UpdateUserLoginInfo(id, ip, t).Unwrap()
}

// updateUserLoginCount 更新登录次数
func (logic *WxAuthLogic) updateUserLoginCount(params ...interface{}) {
	id := params[0].(int) // 用户ID
	dao.NewUserDao().UpdateUserLoginCount(id).Unwrap()
}

// InsertUserLoginLog 记录登录日志
//func (logic *WxAuthLogic) insertUserLoginLog(params ...interface{}) {
//	userModel := params[0].(*users.UserModel)
//	ip := params[1].(string)
//	t := params[2].(dingo.Time)
//
//	lgoinLogModel := loginlogs.LoginLogsModel{
//		LoginTime: t,
//		LoginIp:   ip,
//		UserId:    userModel.ID,
//		IsAdmin:   userModel.IsAdmin,
//		UserName:  userModel.Name,
//		CreateAt:  dingo.Time(time.Now().Unix()),
//	}
//
//	//lgoinLogModel := loginlogs.New()
//	dao.NewLoginLogsDao().InsertLoginLogs(&lgoinLogModel).Unwrap()
//}

func (logic *WxAuthLogic) insertUserLoginLog(params ...interface{}) {
	userModel := params[0].(*users.UserModel)
	ip := params[1].(string)
	t := params[2].(dingo.Time)
	module := params[3].(string)
	desc := params[4].(string)
	phone := params[5].(string)

	lgoinLogModel := loginlogs.LoginLogsModel{
		LoginTime: t,
		LoginIp:   ip,
		UserId:    userModel.ID,
		IsAdmin:   userModel.IsAdmin,
		UserName:  userModel.Name,
		CreateAt:  dingo.Time(time.Now().Unix()),
		Module:    module,
		Desc:      desc,
		Phone:     phone,
	}

	//lgoinLogModel := loginlogs.New()
	dao.NewLoginLogsDao().InsertLoginLogs(&lgoinLogModel).Unwrap()
}

// 获取token
func (logic *WxAuthLogic) HandleGetTokenLogic(openid, appId, unionid string) (*resphelper.WxLoginResp, error) {
	var (
		tokenKey, token, nickName, phone string
		state                                     int8
		err                                       error
	)
	tokenKey = utils.Join(global.Const.Pre.TokenKeyPre, "-Applet-Login-Token", openid)
	var memInfo *membermodel.MembersModel
	if unionid == "" {
		memInfo = memberdao.NewMemberDao().
			GetMemberInfoByOpenidAndAppId(openid, appId).Unwrap().(*membermodel.MembersModel)
	} else {
		memInfo = memberdao.NewMemberDao().GetMemberInfoByOpenidOrUnionid("", unionid).Unwrap().(*membermodel.MembersModel)
	}

	if memInfo.ID > 0 {
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "")
		unionid = memInfo.Unionid
		nickName = memInfo.NickName
		phone = memInfo.Phone
		state = memInfo.State
	} else {
		// 新增用户
		m := membermodel.New().Mutate(
			membermodel.WithXcxOpenid(openid),
			membermodel.WithUnionid(unionid),
			membermodel.WithRegFrom("wx_xcx"),
			membermodel.WithCreateAt(dingo.Time(time.Now().Unix())),
			membermodel.WithUUID(utils.Str2Md5(helper.GenerateUUID())),
			membermodel.WithAppId(appId),
		)
		memInfo := memberdao.NewMemberDao().InsertMember(m).Unwrap().(*membermodel.MembersModel)
		token, err = dingo.GenerateToken(memInfo.ID, memInfo.XcxOpenid, 0, 0, 0, 0, "") // 生成token
		unionid = unionid
		nickName = memInfo.NickName
		state = memInfo.State
	}

	// 将token保存到redis
	global.Rdb.Set(context.Background(), tokenKey, token, time.Hour*24) // 过期时间18小时

	return &resphelper.WxLoginResp{
		Token:    token,
		OpenId:   openid,
		UnionId:  unionid,
		ErrCode:  "",
		ErrMsg:   "",
		NickName: nickName,
		Phone:    phone,
		State:    state,
		//SessionKey: pdata.Get("session_key"),
	}, err
}
